package UILayer;
import java.util.Scanner;
import java.util.Collection;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Iterator;
import CTRLayer.OrderCTR;
import CTRLayer.ProductCTR; // slettes 
import CTRLayer.PersonCTR; // slettes
import ModelLayer.*;

/**
 * This class allows the user to interact with the IT-system. In this class
 * the user can create orders and find orders that already exists.
 * 
 * @author Gruppe 4 
 * @version 4. juni 2012
 */
public class OrderUI
{
    // Instance variables
    private OrderCTR orderCTR; //reference to Order controller in controlLayer
    private ProductCTR productCTR; // slettes
    private PersonCTR personCTR; // slettes
    
    /**
     * The constructor of the class initializes "OrderCTR", which is the class
     * that controls the order use case.
     */
    public OrderUI()
    {
        orderCTR = new OrderCTR();
        productCTR = new ProductCTR();
        personCTR = new PersonCTR();
    }

    /**
     * This method starts the order menu.
     */
    public void start()
    {
        productCTR.testAddNonCompositeProduct(); // slettes
        personCTR.testAddPersons(); // slettes
        orderMenu();
    }
   
    /**
     * This method calls a method according to what the user wishes.
     */
    private void orderMenu()
    {
        boolean exit = false;
        while (!exit)
        {
            int choice = writeOrderMenu();
            switch (choice)
            {
                case 1:
                    startCreateOrder();
                    break;  
                case 2:
                    startFindOrder();
                    break;
                case 3:
                    startListAllOrders();
                    break;
                case 4:
                    startUpdateOrderStatus();
                    break;
                case 5:
                    exit = true;
                    break;
            }
        }
    }
    
    /**
     * This method is the menu that the user sees when he/she enters the
     * part of the program that controls the orders.
     */
    private int writeOrderMenu()
    {
        // makes object keyboard to read input from the screen
        System.out.println('\f');
        Scanner keyboard = new Scanner(System.in);
        System.out.println(" *** Order Menu ***");
        System.out.println(" (1) Create an Order");
        System.out.println(" (2) Find an Order");
        System.out.println(" (3) List all orders");
        System.out.println(" (4) Update status");
        System.out.println(" (5) Exit");
                
        int choice = keyboard.nextInt();
        return choice;
    }
    
    /**
     * This method calls all the methods needed to create an order.
     */
    private void startCreateOrder()
    {
        int orderNo = inputOrderNo();
        orderCTR.createOrder(orderNo);
        addCustomer(orderNo);
        addProduct(orderNo);
        addSalesman(orderNo);
        printOrder(orderNo);
        orderCTR.compareDiscounts(orderCTR.findOrder(orderNo).getOrderNo());
        orderCTR.setCustomerAccount(orderNo);
    }
    
    /**
     * This method adds a customer object to the created order object.
     */
    private void addCustomer(int orderNo)
    {
        System.out.println("Add customer (enter phonenumber):");
        
        boolean ok = false;
        
         while (!ok) {
             try {
                String phoneNo = inputPhoneNo();
                orderCTR.addCustomer(phoneNo, orderNo);
                ok = true;
             } catch (Exception e) {
                System.out.println("The customer was not found, try again.");    
             }
         }
    }
    
    /**
     * This method is used to find a product object, add it to a suborder 
     * and after that add the suborder to the order.
     */
    private void addProduct(int orderNo)
    {
        System.out.println("Add product:");
        int barcode = 0;
        int quantity = inputQuantity();
        int discount = inputDiscount();
        int quantityResult = 0;
        
        // Is the product object found and added correctly?
        boolean ok = false;
        while (!ok) {
            try {
                barcode = inputBarcode();
                quantityResult = orderCTR.addProduct(barcode, quantity, discount, orderNo, 0);
                ok = true;
            } catch (Exception e) {
                System.out.println("Product does not exist, try again.");
            }
        }
        
        // Lets the salesman know if the storeage capacity is exceeded or if
        // the storage is out of products of the same kind.
        if (quantityResult == 1) {
            System.out.println("Quantity Warning - The storage is out of products!");
            System.out.println("Not all products can be delivered now.");
            orderCTR.addProduct(barcode, quantity, discount, orderNo, 1);
            orderNewProducts(barcode);
        } else if (quantityResult == 2) {
            System.out.println("Quantity Warning - storage capacity exceeded!");
            orderCTR.addProduct(barcode, quantity, discount, orderNo, 1);
            orderNewProducts(barcode);
        }
        
        // Asks the user if he/she wants to add more products to the order
        // Or if he/she would like to continue to adding the salesman information.
        Scanner keyboard = new Scanner(System.in);  
        System.out.println(" 1. Add more products:  ");
        System.out.println(" 2. Add salesman:  ");
        int addMore = keyboard.nextInt();
        
        if (addMore == 1) {
            addProduct(orderNo);
        }
        
        // Price and discount is calculated.
        orderCTR.calculateTotalPrice(orderNo);
        orderCTR.calculateMaxDiscount(orderNo);
    }
    
    /**
     * This method allows the user to order new products if needed.
     */
    private void orderNewProducts(int barcode) 
    {
        Scanner keyboard = new Scanner(System.in); 
        System.out.println(" 1. Order new products");
        System.out.println(" 2. Continue without ordering new products");
        int addMore = keyboard.nextInt();
        
        // Adds the new products and lets the user know what the quantity is.
        if(addMore == 1) {
            int quantity = inputQuantity();
            int updatedQuantity = orderCTR.updateQuantity(barcode, quantity);
            System.out.println("The quantity of products is now: " + updatedQuantity);
        }
    }
    
    /**
     * This method allows the user to find existing orders. 
     */    
    private void startFindOrder()
    {
        int orderNo = 0;
        boolean ok = false;
        while (!ok) {
            if (orderNo == 1) break;
            try {
                orderNo = inputOrderNo();
                printOrder(orderNo);
                ok = true;
            } catch (Exception e) {
                System.out.println("\nThe order does not exist, try again. (Or enter 1 to go back).\n");
            }
        }
    }
    
    /**
     * This method prints all orders out on the screen. (Not in full detail)
     */   
    private void startListAllOrders()
    {
        HashMap<Integer, Order> orderList = orderCTR.ListAllOrders();
     
        System.out.println("");
        
        // We call the "values()" method on the HashMap, to get a collection of
        // all the elements in the HashMap.
        Collection c = orderList.values();
        
        // We all "iterator()" to get an iterator over all elements.
        Iterator itr = c.iterator();

        System.out.println('\f');
        
        System.out.println("******************************************************");
        System.out.println("****************     ALL ORDERS    *******************");
        System.out.println("******************************************************");
        
        // We loop through the iterator to get elements
        while(itr.hasNext()) {
            Order order = (Order) itr.next();
            System.out.println("");
            System.out.println("Order No.: " + order.getOrderNo());
            System.out.println("Customer name: " + order.getCustomer().getName() +
                               " Customer phonenumber: " + order.getCustomer().getPhoneNo());
            System.out.println("Salesman name: " + order.getSalesman().getName() + 
                               " Salesman phonenumber: " + order.getSalesman().getPhoneNo());
            
        }
        System.out.println("");
        System.out.println("Enter order no. to show more information: ");
        
        // The user can enter an orderNo to get more information.
        startFindOrder();
    }
    
    /**
     * This method begins the process of updating an order's status.
     */   
    private void startUpdateOrderStatus() 
    {
        int orderNo = inputOrderNo();
        setStatus(orderNo);
    }
    
    /**
     * This method lets the user select what status the order has. 
     */
    private void setStatus(int orderNo) {
        Scanner keyboard = new Scanner(System.in);  
        
        System.out.println("\n0. Created, not packed, not paid");
        System.out.println("1. Not packed, paid");
        System.out.println("2. Packed, not paid");
        System.out.println("3. Packed, paid");
        System.out.println("4. Packed, paid, delivered");
        
        int choice = inputStatus();
        
        if (choice >= 0 && choice <= 4) {            
            orderCTR.setStatus(orderNo, choice);
        } else {
            System.out.print("\nWarning: Enter number between 0-4\n");
            setStatus(orderNo);
        }
    }
    
    /**
     * This method returns what status the user selected for the order.
     */
    private String getStatus(Order order)
    {
        String status = "";
        if (order.getStatus() == 0) {
            status = "Created, not packed, not paid";
        } else if (order.getStatus() == 1) {
            status = "Not packed, paid";
        } else if (order.getStatus() == 2) {
            status = "Packed, not paid";
        } else if (order.getStatus() == 3) {
            status = "Packed, paid";
        } else if (order.getStatus() == 4) {
            status = "Packed, paid, delivered";
        }
        
        return status;
    }
    
    /**
     * This method begins the process of adding a Salesman to an order.
     */   
    private void addSalesman(int orderNo)
    {
        System.out.println("Add salesman (enter phonenumber):");
        String phoneNo = inputPhoneNo();
        orderCTR.addSalesman(phoneNo, orderNo);
    }
    
    /**
     * Start "input methods".
     */   
    private String inputPhoneNo()
    {
         boolean ok = false;
         String phoneNo = "";
        
         while (!ok) {
             try{
                 Scanner keyboard = new Scanner(System.in);
                 System.out.print(" Write Customer PhoneNo:  ");
                 phoneNo = keyboard.nextLine();
                 ok = true;
             } catch (Exception e) {
                 System.out.println("Something went wrong!");
             }
         }
         
         return phoneNo;
    }
    
    private int inputOrderNo()
    {
         boolean ok = false;
         int OrderNo = 0;
         
         while (!ok) {
             try{
                 Scanner keyboard = new Scanner(System.in);
                 System.out.print(" Write OrderNo:  ");
                 OrderNo = keyboard.nextInt();
                 ok = true;
             } catch (Exception e) {
                 System.out.println("It must to be a number!");
             }
         }
         
         return OrderNo;
    }
    
    private int inputBarcode()
    {
         
         boolean ok = false;
         int barcode = 0;
         
         while (!ok) {
             try{
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write barcode:  ");
                 barcode = keyboard.nextInt();
                 ok = true;
             } catch (Exception e) {    
                 System.out.println("It must to be a number!");
             }
         }
         
         return barcode;
    }
    
    private int inputDiscount()
    {
        
         boolean ok = false;
         int discount = 0;

         while (!ok) {
             try{
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Discount (in %):  ");
                 discount = keyboard.nextInt();
                 ok = true;
             } catch (Exception e) {
                 System.out.println("It must to be a number!");
             }
         }       
         
         return discount;                              
    }
    
    private int inputQuantity()
    {
         boolean ok = false;
         int quantity = 0;
         
         while (!ok) {
             try{
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Write Product Quantity:  ");
                 quantity = keyboard.nextInt();
                 ok = true;
             } catch (Exception e) {
                 System.out.println("It must to be a number!"); 
             }
         }
         
         return quantity;
    }
    
    private int inputStatus()
    {
         boolean ok = false;
         int status = 0;
         
         while (!ok) {
             try{
                 Scanner keyboard = new Scanner(System.in);  
                 System.out.print(" Set status:  ");
                 status = keyboard.nextInt();
                 ok = true;
             } catch (Exception e) {
                 System.out.println("\nIt must to be a number!\n"); 
             }
         }
         
         return status;
    }
    /**
     * End "input methods".
     */
    
    /**
     * This method calls methods needed to print the order sheet.
     */
    private void printOrder(int orderNo) {
        Order order = orderCTR.findOrder(orderNo);
        System.out.println('\f');
        System.out.println("");
        printHeadline();
        System.out.println("\n----------------------------------------------------" +
                           "----------------------------------------------------");
        System.out.println("Order no.: " + order.getOrderNo() + 
                         "     Date: " + order.getDate() + 
                         "     Status: " + getStatus(order));
        System.out.println("----------------------------------------------------" +
                           "----------------------------------------------------");
        
        System.out.println("\n----------------------------------------------------" +
                           "----------------------------------------------------");
        printCustomer(order);
        System.out.println("\n----------------------------------------------------" +
                           "----------------------------------------------------");
        printProducts(order);
        System.out.println("\n----------------------------------------------------" +
                           "----------------------------------------------------");
        printSalesman(order);
        System.out.println("\n----------------------------------------------------" +
                           "----------------------------------------------------");
    }
    
    /**
     * Information about the customer are printed.
     */
    private void printCustomer(Order order) {
        System.out.println("");
        System.out.println("Customer information: ");
        System.out.println("");
        System.out.println("Customer name:          " + order.getCustomer().getName());
        System.out.println("Customer address:       " + order.getCustomer().getAddress());
        System.out.println("Customer city:          " + order.getCustomer().getCity());
        System.out.println("Customer postalcode:    " + order.getCustomer().getPostalCode());
        System.out.println("Customer phonenumber:   " + order.getCustomer().getPhoneNo());
        System.out.println("Customer email:         " + order.getCustomer().getEmail());
        System.out.println("Customer type:          " + order.getCustomer().getCustomerType());
    }
    
    /**
     * Information about the products are printed.
     */
    private void printProducts(Order order) {
        ArrayList<SubOrder> subOrders = order.getSubOrders();
        System.out.println("");
        System.out.println("Product information: ");
        
        for (SubOrder subOrder : subOrders) {
         
            // Control what type of product it is.
            if (subOrder.getProduct() instanceof NonCompositeProduct) {
                printNonCompositeProduct(subOrder);
            } else {
                printCompositeProduct(subOrder);
            }
            
        }
        
        System.out.println("\n----------------------------------------------------" +
                           "----------------------------------------------------\n");
        // Prices are printed and discounts are calculated.
        System.out.println("Prices:");
        System.out.println("");
        System.out.println("Total price: " + order.getTotalPrice());
        boolean check = orderCTR.compareDiscounts(order.getOrderNo());
        System.out.println("Craftsman discount: 5%");
        System.out.println("Total price with discounts: " + order.getDiscountPrice());
        if (check) 
            System.out.println("The discount has been regulated to max 20%");
    }
    
    /**
     * This method prints information about a NonCompositeProduct.
     */
    private void printNonCompositeProduct(SubOrder subOrder) {
        
        // Price of all products of same type are calculated.
        double totalPrice = getCurrentPrice(subOrder) * subOrder.getQuantity();
        double Discountprice = totalPrice * ((double) subOrder.getDiscount() / 100);
        Discountprice = totalPrice - Discountprice;           
        
        System.out.println("");
        System.out.println("Product name: " + subOrder.getProduct().getProductName() +
                       "     Barcode: " + subOrder.getProduct().getBarcode() +
                       "     Price " + getCurrentPrice(subOrder));
        System.out.println("Quantity: " + subOrder.getQuantity() + 
                           "     total Price: " + totalPrice +
                           "     Discount: " + subOrder.getDiscount() + 
                           "     Price with discount: " + Discountprice); 
        System.out.println("Missing products: " + subOrder.getMissingProduct());
        
    }
    
    /**
     * The method prints information about a CompositeProduct.
     */
    private void printCompositeProduct(SubOrder subOrder) {
 
        double totalPrice = getCurrentPrice(subOrder) * subOrder.getQuantity();
        double Discountprice = totalPrice * ((double) subOrder.getDiscount() / 100);
        Discountprice = totalPrice - Discountprice;           
        
        System.out.println("");
        System.out.println("Product name: " + subOrder.getProduct().getProductName() +
                       "     Barcode: " + subOrder.getProduct().getBarcode() +
                       "     Price " + getCurrentPrice(subOrder));
        System.out.println("Quantity: " + subOrder.getQuantity() + 
                           "     total Price: " + totalPrice +
                           "     Discount: " + subOrder.getDiscount() +
                           "     Price with discount: " + Discountprice);
        
        CompositeProduct product = (CompositeProduct) subOrder.getProduct();
        
        System.out.println("");
        int index = 0;
        
        // All subproducts are printed.
        for (Partlist child : product.getChildren()) {
             Product subProduct = child.getProduct();
             System.out.println("  - Subproduct name: " + subProduct.getProductName() +
                                "    Subproduct barcode: " + subProduct.getBarcode() +
                                "    Quantity: " + child.getQuanitity() + 
                                "    Missing products: " + subOrder.getMissingProductsComposite().get(index));
             index++;
             
        } 
    }
    
    /**
     * This method checks if there is an offer on a product.
     */
    private double getCurrentPrice(SubOrder subOrder) {
        double price = 0.0;
        if (subOrder.getProduct().getOfferPrice() != 0.0) 
            price = subOrder.getProduct().getOfferPrice();
        else
            price = subOrder.getProduct().getPrice();
            
        return price;
    }
    
    /**
     * This method prints information about the salesman.
     */
    private void printSalesman(Order order) 
    {
        System.out.println("");
        System.out.println("Salesman information: ");
        System.out.println("");
        System.out.println("Salesman name:         " + order.getSalesman().getName());
        System.out.println("Salesman phonenumber:  " + order.getSalesman().getPhoneNo());
        System.out.println("Salesman email:        " + order.getSalesman().getEmail());
        System.out.println("Salesman department:   " + order.getSalesman().getDepartment());
        Scanner sc = new Scanner(System.in);
        while(!sc.nextLine().equals(""));
    }
    
    /**
     * This method prints the header of the order sheet / invoice.
     */
    private void printHeadline()
    {
        System.out.println("                        ******************************************************");
        System.out.println("                        ******************     INVOICE    ********************");
        System.out.println("                        ******************************************************");
    }
    
}